using Abp.Application.Services.Dto;
using Abp.Domain.Entities.Auditing;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yozeev.BusinessLogic;
using Yozeev.BusinessLogic.Stats.Dtos;
using Yozeev.Common;
using Yozeev.Controllers.Stats.Filters;
using Yozeev.Dtos;

namespace Yozeev.Controllers.Stats
{
    /// <summary>
    /// 航班售票统计
    /// </summary>
    [Route("api/Stats/[Controller]/[Action]")]
    public class ScheduleTicketController : YozeevControllerBase
    {
        private readonly IRepository<Schedule, Guid> _scheduleRep;

        private readonly IRepository<Boat, Guid> _boatRep;

        private readonly IRepository<Activity, Guid> _activityRep;

        private readonly IRepository<ActivityDetail, Guid> _activityDetailRep;

        private readonly IRepository<Route, Guid> _routeRep;

        private readonly IRepository<TicketPrice, Guid> _ticketPriceRep;

        private readonly IRepository<TicketDetail, Guid> _ticketDetailRep;

        private readonly IRepository<Ticket, Guid> _ticketRep;

        private readonly AbstractFilter _routeFilter;

        private readonly AbstractFilter _boatFilter;

        private readonly AbstractFilter _ticketTypeFilter;

        private readonly IQueryHelper _queryHelper;

        public ScheduleTicketController(IRepository<Schedule, Guid> scheduleRep,
            IRepository<Boat, Guid> boatRep, IRepository<Activity, Guid> activityRep,
            IQueryHelper queryHelper, IRepository<Route, Guid> routeRep,
            IRepository<TicketDetail, Guid> ticketDetailRep,
            IRepository<TicketPrice, Guid> ticketPriceRep,
            IRepository<Ticket, Guid> ticketRep,
            RouteFilter routeFilter,
            TicketTypeFilter ticketTypeFilter,
            BoatFilter boatFilter,
            IRepository<ActivityDetail, Guid> activityDetail)
        {
            _activityDetailRep = activityDetail;
            _scheduleRep = scheduleRep;
            _boatRep = boatRep;
            _activityRep = activityRep;
            _routeRep = routeRep;
            _ticketDetailRep = ticketDetailRep;
            _ticketRep = ticketRep;
            _ticketPriceRep = ticketPriceRep;
            _routeFilter = routeFilter;
            _ticketTypeFilter = ticketTypeFilter;
            _boatFilter = boatFilter;
            _queryHelper = queryHelper;
        }

        /// <summary>
        /// 航班售票统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<StatsPagedResultDto<ScheduleTicketResultDto>> GetPagedStat(ScheduleTicketInput input, string ticketId)
        {
            var schedules = _scheduleRep.GetAll().Where(_queryHelper.WhereExp<Schedule>(input.queryData));
            var activities = _activityRep.GetAll();
            var boats = _boatRep.GetAll();
            var routes = _routeRep.GetAll();

            if (!string.IsNullOrEmpty(ticketId))
            {
                var ticketPriceIds = _ticketPriceRep.GetAll()
                    .Where(t => t.TicketId.ToString().Equals(ticketId)).Select(t => t.Id).ToList();
                var activityIds = _activityDetailRep.GetAll()
                    .Where(a => ticketPriceIds.Contains(a.TicketPriceId))
                    .Select(a => a.ActivityId)
                    .ToList();
                activities = activities.Where(a => activityIds.Contains(a.Id));
            }

            var acts = from activity in activities
                       where activity.PayStatus == PayStatusEnum.PayStatusPayment || activity.PayStatus == PayStatusEnum.PayStatusRefund
                       group activity by activity.ScheduleId
                       into groups
                       select new
                       {
                           ScheduleId = groups.Key,
                           SaleAmount = groups.Sum(acitivity => acitivity.ActivityType == ActivityTypeEnum.ActivityTypePayment ? acitivity.TotalAmount : 0),
                           RefundAmount = groups.Sum(acitivity => acitivity.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? acitivity.TotalAmount : 0),
                           TotalAmount = groups.Sum(activity => activity.TotalAmount),
                           SaleCount = groups.Sum(acitivity => acitivity.ActivityType == ActivityTypeEnum.ActivityTypePayment ? acitivity.TotalQuantity : 0),
                           RefundCount = groups.Sum(acitivity => acitivity.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? acitivity.TotalQuantity : 0),
                           TotalCount = groups.Sum(activity => activity.ActivityType == ActivityTypeEnum.ActivityTypePayment ? activity.TotalQuantity : 0) -
                             groups.Sum(activity => activity.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? activity.TotalQuantity : 0)
                       };

            var sch = from schedule in schedules
                      orderby schedule.CreationTime descending
                           select new
                           {
                               schedule,
                               schedule.Route,
                               schedule.Boat
                           };

            var result = from act in acts
                         join schedule in sch
                         on act.ScheduleId equals schedule.schedule.Id
                         select new ScheduleTicketResultDto
                         {
                             Schedule = schedule.schedule,
                             Boat = schedule.Boat,
                             Route = schedule.Route,
                             SaleAmount = act.SaleAmount,
                             RefundAmount = act.RefundAmount,
                             TotalAmount = act.TotalAmount,
                             SaleCount = act.SaleCount,
                             RefundCount = act.RefundCount,
                             TotalCount = act.TotalCount,
                         };

            var count = result.Count();
            Dictionary<string, IEnumerable<object>> filters = new Dictionary<string, IEnumerable<object>>();
            _boatFilter.Decorate(filters);
            _ticketTypeFilter.Decorate(filters);
            _routeFilter.Decorate(filters);
            return new StatsPagedResultDto<ScheduleTicketResultDto>(count, result.AsQueryable().PageBy(input).ToList(), filters);
        }

        /// <summary>
        /// 航班售票详情
        /// </summary>
        /// <param name="scheduleId"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PagedResultDto<ScheduleTicketDetailResultDto>> ScheduleDetailStat(string scheduleId)
        {
            var ticketDetails = _ticketDetailRep.GetAll().Where(s => s.ScheduleId.ToString() == scheduleId);
            var tickets = _ticketRep.GetAll();

            var result = from ticketDetail in ticketDetails
                         select new ScheduleTicketDetailResultDto
                         {
                             Ticket = (from ticket in tickets
                                      where ticket.Id == ticketDetail.TicketId select ticket).FirstOrDefault(),
                             SalePrice = ticketDetail.ActivityDetail.SalePrice,
                             Schedule = ticketDetail.Schedule,
                             Customer = ticketDetail.Customer,
                             TicketDetail = ticketDetail
                         };

            var count = result.Count();
            return new PagedResultDto<ScheduleTicketDetailResultDto>(count, result.ToList());
        }
    }
}
